#include"fd_manager.h"
#include"hook.h"

namespace yuechuan {

    FdCtx::FdCtx(int fd)
            : m_isInit(false),
              m_isSocket(false),
              m_sysNonblock(false),
              m_userNonblock(false),
              m_isClose(false),
              m_fd(fd),
              m_recvTimeout(-1),
              m_sendTimeout(-1) {
        init();
    }

    FdCtx::~FdCtx() {

    }

    void FdCtx::setTimeout(int type, uint64_t v) {
        if (type == SO_RCVTIMEO) {// 复用SOCKET中的内置参数来判断是接受超时还是发送超时
            m_recvTimeout = v;
        } else {
            m_sendTimeout = v;
        }
    }

    uint64_t FdCtx::getTimeout(int type) {// 获取文件句柄的超时时间
        if (type == SO_RCVTIMEO) {
            return m_recvTimeout;
        } else {
            return m_sendTimeout;
        }
    }

    bool FdCtx::init() {
        if (m_isInit) {
            return true;
        }
        m_recvTimeout = -1;
        m_sendTimeout = -1;
        struct stat fd_state;
        if (-1 == fstat(m_fd, &fd_state)) {
            m_isInit = false;
            m_isSocket = false;
        } else {
            m_isInit = true;
            // fd_state.st_mode & 0170000 == 0140000    // 对应的句柄是sock的话，对应的mode就是0140000得到的结果就为true
            m_isSocket = S_ISSOCK(fd_state.st_mode);
        }

        if (m_isSocket) {
            // get File Status Flag 查看文件状态，将当是sock类型时将文件设置为非阻塞，这里的fcntl_f是对应系统调用中的fcntl
            int flags = fcntl_f(m_fd, F_GETFL, 0);
            if (!(flags & O_NONBLOCK)) {
                fcntl_f(m_fd, F_SETFL, flags | O_NONBLOCK);    // 设置sock文件类型为非阻塞状态
            }
            m_sysNonblock = true;
        } else {
            m_sysNonblock = false;
        }
        m_userNonblock = false;
        m_isClose = false;
        return m_isInit;
    }

    FdManager::FdManager() {
        m_datas.resize(64);

    }

    FdManager::~FdManager() {

    }

    FdCtx::ptr FdManager::get(int fd, bool auto_create) {
        if( fd == -1){
            return nullptr;
        }
        RWMutexType::ReadLock lock(m_mutex);
        if (m_datas.size() <= (size_t) fd) {
            if (!auto_create) {
                return nullptr;
            }
        } else {
            if (m_datas[fd] || !auto_create) {
                // auto_create为false时，对于已经释放管理的句柄可以将其作为nullptr进行返回，如果为true时，要在这个函数中创建该文件句柄
                return m_datas[fd];
            }
        }
        lock.unlock();
        RWMutexType::WriteLock lock2(m_mutex);
        FdCtx::ptr ctx(new FdCtx(fd));
        m_datas[fd] = ctx;
        return ctx;

    }

    void FdManager::del(int fd) {
        RWMutexType::WriteLock lock(m_mutex);
        if (m_datas.size() <= (size_t) fd) {
            return;
        }
        m_datas[fd].reset();
    }

} // namespace yuechuan
